package org.example.doctorapi.aspectMethods;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.example.doctorapi.data.SysOperLog;
import org.example.doctorapi.data.SysUser;
import org.example.doctorapi.mapper.SysUserMapper;
import org.example.doctorapi.server.SysOperLogServer;
import org.example.doctorapi.util.ServletUtils;
import org.example.doctorcommon.util.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.util.stream.Collectors;

@Component
@Aspect
public class LogAspect {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysOperLogServer sysOperLogServer;
    @Pointcut("@annotation(org.example.doctorapi.aspectMethods.LogAnnotation)")
    public void logPointCut(){}

   /* @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("切面around");
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        String token = request.getHeader("token");
        System.out.println("token"+token);
        // 获取RequestBody参数
        //String requestBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
        //JSONObject requestParam = StringUtils.isBlank(requestBody) ? JSONUtil.createObj() : JSONUtil.parseObj(requestBody);
        return joinPoint.proceed();
    }*/

    @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
        System.out.println("切面After");
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        String token = request.getHeader("token");
        String verifyName = JwtUtils.verifyName(token);
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(verifyName),"user_name",verifyName);
        SysUser sysUser = sysUserMapper.selectOne(queryWrapper);
        System.out.println("user"+sysUser);
        handleLog(joinPoint, null, jsonResult,sysUser);
    }
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e){
        handleLog(joinPoint, e, null,null);
    }


    protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult,SysUser sysUser){
        LogAnnotation annotation = getAnnotationLog(joinPoint);
        if (annotation == null){
            return;
        }
        SysOperLog operLog = new SysOperLog();
        operLog.setJsonResult(JSON.toJSONString(jsonResult));
        operLog.setOperName(sysUser.getUserName());
        // 设置方法名称
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        operLog.setMethod(className + "." + methodName + "()");
        operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
        //设置操作时间
        operLog.setOperTime(DateUtil.date());
        operLog.setStatus("0");
        sysOperLogServer.insertOperLog(operLog);
    }

    private LogAnnotation getAnnotationLog(JoinPoint joinPoint){
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        if (method != null && method.isAnnotationPresent(LogAnnotation.class)){
            return method.getAnnotation(LogAnnotation.class);
        }
        return null;
    }
}
